package rexsee.core.style;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;

import rexsee.core.utilities.Utilities;
import android.graphics.AvoidXfermode;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.PathEffect;
import android.graphics.PixelXorXfermode;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;

public class PaintSheet {

	public String mode = "none";

	public String alpha = "1"; //0~1

	public String antialias = "false";
	public String dither = "false";
	public String filterbitmap = "false";

	public String tolerance = "0"; //int
	public String op_color = "#888888";

	public String color = "#FFFFFF";
	public String font_size = "14"; //float
	public String font_weight = "normal"; //normal|bold
	public String text_decoration = "normal"; //normal|underline|strikethru
	public String text_align = "left"; //left|center|right
	public String text_shadow_radius = "0"; //float
	public String text_shadow_dx = "0"; //float
	public String text_shadow_dy = "0"; //float
	public String text_shadow_color = "#000000"; //String|int
	public String text_scalex = "1";
	public String text_skewx = "0";
	public String text_linear = "false";
	public String text_subpixel = "false";

	public String format = "fillandstroke";
	public String stroke_width = "1";
	public String stroke_style = "solid";
	public String stroke_cap = "butt";
	public String stroke_join = "bevel";
	public String stroke_join_meter = "0";

	private String[] split(String value, int n) {
		if (n <= 0) return null;
		String[] rtn = new String[n];
		String[] v = value.split("\\ ");
		rtn[0] = v[0];
		for (int i = 1; i < n; i++) {
			if (v.length > i) rtn[i] = v[i];
			else rtn[i] = rtn[i - 1];
		}
		return rtn;
	}
	private PorterDuff.Mode getPorterDuffMode() {
		PorterDuff.Mode m;
		try {
			m = PorterDuff.Mode.valueOf(mode);
			return (m == null) ? PorterDuff.Mode.SRC : m;
		} catch (Exception e) {
			return PorterDuff.Mode.SRC;
		}
	}
	private PathEffect getPathEffect() {
		float w = Utilities.getFloat(stroke_width, 1);
		if (stroke_style.equalsIgnoreCase("dot")) {
			return new DashPathEffect(new float[]{w, w}, 0);
		} else if (stroke_style.equalsIgnoreCase("shortdash")) {
			return new DashPathEffect(new float[]{w * 2, w}, 0);
		} else if (stroke_style.equalsIgnoreCase("dash")) {
			return new DashPathEffect(new float[]{w * 4, w}, 0);
		} else if (stroke_style.equalsIgnoreCase("longdash")) {
			return new DashPathEffect(new float[]{w * 8, w}, 0);
		} else if (stroke_style.equalsIgnoreCase("dotshortdash")) {
			return new DashPathEffect(new float[]{w * 2, w, w, w}, 0);
		} else if (stroke_style.equalsIgnoreCase("dotdash")) {
			return new DashPathEffect(new float[]{w * 4, w, w, w}, 0);
		} else if (stroke_style.equalsIgnoreCase("dotlongdash")) {
			return new DashPathEffect(new float[]{w * 8, w, w, w}, 0);
		} else {
			return null;
		}
	}

	@Override
	public PaintSheet clone() {
		PaintSheet rtn = new PaintSheet();
		Field[] fields = this.getClass().getFields();
		for (int i = 0; i < fields.length; i++) {
			try {
				fields[i].set(rtn, fields[i].get(this));
			} catch (Exception e) {
			}
		}
		return rtn;
	}

	public PaintSheet parse(String style) {
		String[] argus = style.split(";");
		for (int i = 0; i < argus.length; i++) {
			if (argus[i].indexOf(":") <= 0) continue;
			String key = argus[i].substring(0, argus[i].indexOf(":")).trim().toLowerCase().replaceAll("\\-", "\\_");
			String value = argus[i].substring(argus[i].indexOf(":") + 1).trim();
			if (value.length() == 0) continue;
			if (key.equals("text_shadow")) {
				String[] tmp = split(value, 4);
				text_shadow_radius = tmp[0];
				text_shadow_dx = tmp[1];
				text_shadow_dy = tmp[2];
				text_shadow_color = tmp[3];
			} else {
				try {
					this.getClass().getField(key).set(this, value);
				} catch (Exception e) {
				}
			}
		}
		return this;
	}
	public PaintSheet parse(HashMap<String, String> map) {
		Iterator<String> iterator = map.keySet().iterator();
		while (iterator.hasNext()) {
			String key = iterator.next().trim().toLowerCase().trim().toLowerCase().replaceAll("\\-", "\\_");
			String value = map.get(key).trim();
			if (value == null) continue;
			if (value.length() == 0) continue;
			if (key.equals("text_shadow")) {
				String[] tmp = split(value, 4);
				text_shadow_radius = tmp[0];
				text_shadow_dx = tmp[1];
				text_shadow_dy = tmp[2];
				text_shadow_color = tmp[3];
			} else {
				try {
					this.getClass().getField(key).set(this, value);
				} catch (Exception e) {
				}
			}
		}
		return this;
	}

	public Paint getPaint() {

		/*
		 * setHinting(int mode)
		 * setTypeface (Typeface typeface)
		 * setRasterizer(Rasterizer rasterizer)
		 */

		//setMaskFilter(MaskFilter maskfilter)
		//setColorFilter(ColorFilter filter)
		//setShader (Shader shader)

		Paint paint = new Paint();
		paint.setAntiAlias(antialias.equalsIgnoreCase("true"));
		paint.setDither(dither.equalsIgnoreCase("true"));
		paint.setFilterBitmap(filterbitmap.equalsIgnoreCase("true"));
		paint.setLinearText(text_linear.equalsIgnoreCase("true"));
		paint.setLinearText(text_subpixel.equalsIgnoreCase("true"));
		paint.setColor(RexseeDrawable.getIntColor(color));
		paint.setTextSize(Utilities.getInt(font_size.toLowerCase().replaceAll("px", ""), 24));
		paint.setFakeBoldText(font_weight.equals("bold"));
		paint.setTextScaleX(Utilities.getFloat(text_scalex, 1));
		paint.setTextSkewX(Utilities.getFloat(text_skewx, 0));
		float radius = Utilities.getFloat(text_shadow_radius, 0);
		float dx = Utilities.getFloat(text_shadow_dx, 0);
		float dy = Utilities.getFloat(text_shadow_dy, 0);
		int color = RexseeDrawable.getIntColor(text_shadow_color);
		paint.setShadowLayer(radius, dx, dy, color);
		if (text_align.equalsIgnoreCase("right")) {
			paint.setTextAlign(Align.RIGHT);
		} else if (text_align.equalsIgnoreCase("center")) {
			paint.setTextAlign(Align.CENTER);
		} else {
			paint.setTextAlign(Align.LEFT);
		}
		if (text_decoration.equalsIgnoreCase("underline")) {
			paint.setUnderlineText(true);
		} else if (text_decoration.equalsIgnoreCase("strikethru") || text_decoration.equalsIgnoreCase("strikethrough")) {
			paint.setStrikeThruText(true);
		}

		float a = Utilities.getFloat(alpha, 0);
		if (a > 1) a = 1;
		if (a < 0) a = 0;
		paint.setAlpha((int) a * 255);

		paint.setStyle(format.equalsIgnoreCase("stroke") ? Paint.Style.STROKE : (format.equalsIgnoreCase("fill") ? Paint.Style.FILL : Paint.Style.FILL_AND_STROKE));
		if (!format.equalsIgnoreCase("fill")) {
			float strokeWidth = Utilities.getFloat(stroke_width, -1);
			if (strokeWidth > 0) {
				paint.setStrokeWidth(strokeWidth);
				PathEffect pathEffect = getPathEffect();
				if (pathEffect != null) paint.setPathEffect(pathEffect);
			}
			paint.setStrokeCap(stroke_cap.equalsIgnoreCase("round") ? Paint.Cap.ROUND : (stroke_cap.equalsIgnoreCase("square") ? Paint.Cap.SQUARE : Paint.Cap.BUTT));
			paint.setStrokeJoin(stroke_join.equalsIgnoreCase("bevel") ? Paint.Join.BEVEL : (stroke_join.equalsIgnoreCase("round") ? Paint.Join.ROUND : Paint.Join.MITER));
			paint.setStrokeMiter(Utilities.getFloat(stroke_join_meter, 0));
		}

		if (mode.equalsIgnoreCase("none")) {
		} else if (mode.equalsIgnoreCase("avoid")) {
			paint.setXfermode(new AvoidXfermode(RexseeDrawable.getIntColor(op_color), Utilities.getInt(tolerance, 0), AvoidXfermode.Mode.AVOID));
		} else if (mode.equalsIgnoreCase("target")) {
			paint.setXfermode(new AvoidXfermode(RexseeDrawable.getIntColor(op_color), Utilities.getInt(tolerance, 0), AvoidXfermode.Mode.TARGET));
		} else if (mode.equalsIgnoreCase("pixelxor")) {
			paint.setXfermode(new PixelXorXfermode(RexseeDrawable.getIntColor(op_color)));
		} else {
			paint.setXfermode(new PorterDuffXfermode(getPorterDuffMode()));
		}

		return paint;
	}

}
